package ru.pbem.olympia.battles;

import java.util.ArrayList;
import java.util.List;

/**
 * User: roman.pavlov
 * Date: 22-Sep-2010
 * Time: 15:18:42
 */
public class G3Army implements Army {
    private FightingUnit commander;
    private FightingUnit shelter;
    private List<List<FightingUnit>> units;
    private boolean fightToDeath;

    public G3Army(final Combatant commander, final List<List<Combatant>> combatants, final Building shelter, final boolean fightToDeath) {
        this.commander = new Fighter(commander, null);
        int seatsInShelter = 0;
        if (shelter != null){
            this.shelter = new Fighter(shelter, null);
            seatsInShelter = shelter.getSize();
        }
        this.units = new ArrayList<List<FightingUnit>>();
        for(List<Combatant> line: combatants){
            ArrayList<FightingUnit> fightingLine = new ArrayList<FightingUnit>();
            for(Combatant combatant: line){
                fightingLine.add(new Fighter(combatant, seatsInShelter > 0 ? this.shelter : null));
                seatsInShelter--;
            }
            units.add(fightingLine);
        }
        this.fightToDeath = fightToDeath;
    }

    @Override
    public boolean isAbleToFight() {
        long total = 0L;
        long lost = 0L;
        for (final List<FightingUnit> line : units) {
            for (final FightingUnit unit : line) {
                final long unitStrength = unit.getEffectiveOffense(true) + unit.getEffectiveDefense(true);
                total += unitStrength;
                if (!unit.isAlive()) {
                    lost += unitStrength;
                }
            }
        }
        return total > (fightToDeath ? lost :  2 * lost);
    }

    @Override
    public List<FightingUnit> getAttackers() {
        return getActiveCombatants(true);
    }

    @Override
    public List<FightingUnit> getTargets(boolean siegeDeviceAttack) {
        final List<FightingUnit> victims = new ArrayList<FightingUnit>();
        if (!siegeDeviceAttack){
            victims.addAll(getActiveCombatants(false));
            if (victims.size() > 1 && victims.contains(commander)) {
                victims.remove(commander);
            }
        }
        if (shelter != null && shelter.isAlive()) {
            victims.add(shelter);
        }
        return victims;
    }

    @Override
    public List<FightingUnit> getUnits() {
        List<FightingUnit> result = new ArrayList<FightingUnit>();
        for (List<FightingUnit> line: units){
            result.addAll(line);
        }
        return result;
    }

    protected List<FightingUnit> getActiveCombatants(final boolean addRanged) {
        final List<FightingUnit> units = new ArrayList<FightingUnit>(0);
        boolean firstLine = true;
        for (final List<FightingUnit> line : this.units) {
            for (final FightingUnit unit : line) {
                if (unit.isAlive()) {
                    if (firstLine){
                        unit.moveToFirstLine();
                        units.add(unit);
                    } else if (addRanged && unit.getEffectiveOffense(false) > 0){
                        units.add(unit);
                    }
                }
            }
            firstLine = units.isEmpty() || units.size() == 1 && units.contains(commander);
        }
        return units;
    }

    @Override
    public String toString() {
        return "G3Army{" +
                "commander=" + this.commander +
                ", shelter=" + this.shelter +
                ", units=" + getUnits().size() +
                ", fightToDeath=" + this.fightToDeath +
                '}';
    }
}
